/***************************************************************************
 *   Copyright (C) 2006-2009 by Dead_Body   *
 *   jamesholodnak@gmail.com   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <stdio.h>
#include <string.h>
#include "defines.h"
#include "pce/pce.h"
#include "pce/state/state.h"
#include "pce/state/blocks.h"
#include "system/file.h"

int pce_loadstate(int fp)
{
	stateheader_t header;
	blockpce_t *bpce;
	blockcpu_t *cpu;
	blockbram_t *bram;
	int i;
	void *block;
	int blocktype;

	//load state header
	if(blocks_loadheader(fp,&header) != 0)
		return(1);

	//enumerate thru all the state blocks
	while((block = blocks_load(fp,&blocktype)) != 0) {
		switch(blocktype) {
			case B_PCE:
				bpce = (blockpce_t*)block;
/*				memcpy(nes->ram,bnes->ram,0x800);
				memcpy(nes->nametables[0],bnes->nametables + 0x000,0x400);
				memcpy(nes->nametables[1],bnes->nametables + 0x400,0x400);
				memcpy(nes->nametables[2],bnes->nametables + 0x800,0x400);
				memcpy(nes->nametables[3],bnes->nametables + 0xC00,0x400);
				memcpy(nes->pal,bnes->palette,32);
				nes->strobe = bnes->strobe;
				for(i=0;i<32;i++)
					pal_write(i,nes->pal[i]);*/
				break;
			case B_CPU:
				cpu = (blockcpu_t*)block;
				pce->cpu.a = cpu->a;
				pce->cpu.x = cpu->x;
				pce->cpu.y = cpu->y;
				pce->cpu.s = cpu->s;
				pce->cpu.f = cpu->f;
				pce->cpu.pc = cpu->pc;
				pce->cpu.cycles = cpu->cycles;
				pce->cpu.needirq = cpu->irq;
				break;
			case B_BRAM:
				bram = (blockbram_t*)block;
				if(pce->rom->bramdata)
					memcpy(pce->rom->bramdata,bram->data,pce->rom->bramsize);
				break;
		}
		blocks_free(block);
		log_message("loading block '%s'\n",blockids[blocktype]);
	}

	log_message("loaded state, %ld bytes\n",file_tell(fp));

	return(0);
}

int pce_savestate(int fp)
{
	int i;
	state_t state;

	memset(&state,0,sizeof(state_t));
/*
	memcpy(state.nes.ram,nes->ram,0x800);
	memcpy(state.nes.nametables + 0x000,nes->nametables[0],0x400);
	memcpy(state.nes.nametables + 0x400,nes->nametables[1],0x400);
	memcpy(state.nes.nametables + 0x800,nes->nametables[2],0x400);
	memcpy(state.nes.nametables + 0xC00,nes->nametables[3],0x400);
	memcpy(state.nes.palette,nes->pal,32);
	state.nes.strobe = nes->strobe;

	state.cpu.a = nes->cpu.a;
	state.cpu.x = nes->cpu.x;
	state.cpu.y = nes->cpu.y;
	state.cpu.s = nes->cpu.s;
	state.cpu.f = nes->cpu.f;
	state.cpu.pc = nes->cpu.pc;
	state.cpu.cycles = nes->cpu.totalcycles;
	state.cpu.irq = nes->cpu.needirq;
*/

	if(pce->rom->bramsize) {
		state.bram.size = pce->rom->bramsize;
		memcpy(state.bram.data,pce->rom->bramdata,state.bram.size);
	}

	//write out the save state header
	blocks_saveheader(fp);

	//write save state data
	blocks_savestate(fp,&state);

	log_message("saved state, %ld bytes\n",file_tell(fp));

	return(0);
}

int nes_savebramstate(int fp)
{
	blockbram_t bram;

	if((bram.size = pce->rom->bramsize) == 0)
		return(0);
	blocks_saveheader(fp);
	memcpy(bram.data,pce->rom->bramdata,pce->rom->bramsize);
	blocks_save(fp,B_BRAM,&bram);
	blocks_save(fp,B_END,0);
	return(0);
}
